﻿namespace HostTracker.Azure.Management

open System
open System.ServiceModel
open System.ServiceModel.Web
open System.Runtime.Serialization
open System.Net
open HostTracker.Azure.Management.FSharpExtensions

(*
<?xml version="1.0" encoding="utf-8"?>
<HostedService xmlns="http://schemas.microsoft.com/windowsazure">
  <Url>hosted-service-url</Url>
  <ServiceName>hosted-service-name</ServiceName>
  <HostedServiceProperties>
    <Description>description</Description>
    <Location>location</Location>
    <AffinityGroup>affinity-group</AffinityGroup>
    <Label>base-64-encoded-name-of-the-service</Label>
  </HostedServiceProperties>
  <Deployments>
    <Deployment>
      <Name>deployment-name</Name>
      <DeploymentSlot>deployment-slot</DeploymentSlot>
      <PrivateID>deployment-id</PrivateID>
      <Status>deployment-status</Status>
      <Label>base64-encoded-deployment-label</Label>
      <Url>deployment-url</Url>
      <Configuration>base-64-encoded-configuration-file</Configuration>
      <RoleInstanceList>
        <RoleInstance>
          <RoleName>role-name</RoleName>
          <InstanceName>role-instance-name</InstanceName>
          <InstanceStatus>instance-status</InstanceStatus>
        </RoleInstance>
      </RoleInstanceList>
      <UpgradeDomainCount>upgrade-domain-count</UpgradeDomainCount>
      <RoleList>
        <Role>
          <RoleName>role-name</RoleName>
          <OsVersion>operating-system-version</OsVersion>
        </Role>
      </RoleList>
      <SdkVersion>sdk-version-used-to-create-package</SdkVersion>
      <InputEndpointList>
         <InputEndpoint>
            <RoleName>role-name</RoleName>
            <Vip>virtual-ip-address</Vip>
            <Port>port-number</Port>
         </InputEndpoint>
         …
      </InputEndpointList>
      <Locked>deployment-write-allowed-status</Locked>
      <RollbackAllowed>rollback-operation-allowed</RollbackAllowed>
    </Deployment>
  </Deployments>
</HostedService>
*)
[<DataContract(Name = "HostedServiceProperties", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceProperties() =
    let mutable desc = ""
    let mutable location = ""
    let mutable affinityGroup = ""
    let mutable label = ""
    [<DataMember(Name = "Description", Order = 1)>]
    member x.Desc with get () = desc and set v = desc <- v
    [<DataMember(Name = "Location", Order = 2, IsRequired = false)>]
    member x.Location with get () = location and set v = location <- v
    [<DataMember(Name = "AffinityGroup", Order = 2, IsRequired = false)>]
    member x.AffinityGroup with get () = affinityGroup and set v = affinityGroup <- v
    [<DataMember(Name = "Label", Order = 3)>]
    member private x.LabelEncoded with get () = label.ToBase64() and set (v:string) = label <- v.FromBase64()
    member x.Label =label

[<CollectionDataContract(Name = "Deployments", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceDeployments() = inherit System.Collections.Generic.List<Deployment>()

[<DataContract(Name = "HostedService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedService() =
    let mutable url = ""
    let mutable name = ""
    let mutable props = HostedServiceProperties()
    let mutable deployments = HostedServiceDeployments()
    [<DataMember(Name = "Url", Order = 1)>]
    member x.Url with get () = url and set v = url <- v
    [<DataMember(Name = "ServiceName", Order = 2)>]
    member x.ServiceName with get () = name and set v = name <- v
    [<DataMember(Name = "HostedServiceProperties", Order = 3, IsRequired = false)>]
    member x.Properties with get () = props and set v = props <- v
    [<DataMember(Name = "Deployments", Order = 4, IsRequired = false)>]
    member x.Deployments with get () = deployments and set v = deployments <- v

[<CollectionDataContract(Name = "HostedServices", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServices() = inherit System.Collections.Generic.List<HostedService>()

(*
<?xml version="1.0" encoding="utf-8"?>
<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure">
  <ServiceName>service-name</ServiceName>
  <Label>base64-encoded-service-label</Label>
  <Description>description</Description> // optional
  <Location>location</Location>
  <AffinityGroup>affinity-group</AffinityGroup>
</CreateHostedService>
*)
[<DataContract(Name = "CreateHostedService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceCreation(name: string, label: string, desc: string) = 
    [<DataMember(Name = "ServiceName", Order = 1)>]
    member private x.ServiceName with get () = name and set _ = ()
    [<DataMember(Name = "Label", Order = 2)>]
    member private x.LabelEncoded with get () = label.ToBase64() and set _ = ()
    [<DataMember(Name = "Description", Order = 3)>]
    member private x.Desc with get () = desc and set _ = ()

[<DataContract(Name = "CreateHostedService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceCreationWithAffinityGroup(name, label, desc, affinityGroup: string) = 
    inherit HostedServiceCreation(name, label, desc)
    [<DataMember(Name = "AffinityGroup", Order = 4)>]
    member private x.AffinityGroup with get () = affinityGroup and set _ = ()

[<DataContract(Name = "CreateHostedService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceCreationWithLocation(name, label, desc, location: string) = 
    inherit HostedServiceCreation(name, label, desc)
    [<DataMember(Name = "Location", Order = 4)>]
    member private x.Location with get () = location and set _ = ()

(*
<?xml version="1.0" encoding="utf-8"?>
<UpdateHostedService xmlns="http://schemas.microsoft.com/windowsazure">
  <Label>base64-encoded-service-label</Label>
  <Description>description</Description>
</UpdateHostedService>
*)
[<DataContract(Name = "UpdateHostedService", Namespace = "http://schemas.microsoft.com/windowsazure")>]
type HostedServiceUpdate (label: string, desc: string) =
    [<DataMember(Name = "Label", Order = 1)>]
    member private x.Label with get () = label.ToBase64() and set _ = ()
    [<DataMember(Name = "Description", Order = 2)>]
    member x.Description with get () = desc and set _ = ()

[<Interface>]
[<ServiceContractAttribute>]
type IHostedServiceManagement =
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices", Method="GET")>]
    abstract ListHostedServices: unit -> HostedServices
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginListHostedServices: callback: AsyncCallback * state: obj -> IAsyncResult
    abstract EndListHostedServices: result: IAsyncResult -> HostedServices
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}?embed-detail={withDetails}", Method="GET")>]
    abstract GetHostedService: serviceName:string*withDetails:bool -> HostedService
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginGetHostedService: serviceName:string*withDetails:bool*callback:AsyncCallback*state:obj -> IAsyncResult
    abstract EndGetHostedService: result: IAsyncResult -> HostedService
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices", Method="POST")>]
    abstract CreateHostedServiceWithAffinityGroup: creation:HostedServiceCreationWithAffinityGroup -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginCreateHostedServiceWithAffinityGroup: creation:HostedServiceCreationWithAffinityGroup * callback: AsyncCallback * state: obj -> IAsyncResult
    abstract EndCreateHostedServiceWithAffinityGroup: result: IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices", Method="POST")>]
    abstract CreateHostedServiceInLocation: creation:HostedServiceCreationWithLocation -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginCreateHostedServiceInLocation: creation:HostedServiceCreationWithLocation * callback: AsyncCallback * state: obj -> IAsyncResult
    abstract EndCreateHostedServiceInLocation: result: IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}", Method="DELETE")>]
    abstract DeleteHostedService: serviceName:string -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginDeleteHostedService: serviceName:string * callback: AsyncCallback * state: obj -> IAsyncResult
    abstract EndDeleteHostedService: result: IAsyncResult -> unit
    [<OperationContract>]
    [<WebInvoke(UriTemplate="/services/hostedservices/{serviceName}", Method="PUT")>]
    abstract UpdateHostedService: serviceName:string * update: HostedServiceUpdate -> unit
    [<OperationContract(AsyncPattern = true)>]
    abstract BeginUpdateHostedService: serviceName:string * update: HostedServiceUpdate * callback: AsyncCallback * state: obj -> IAsyncResult
    abstract EndUpdateHostedService: result: IAsyncResult -> unit